/*
 * Copyright (c) 2010 Marc Poppleton
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.marcpoppleton.strawberry.provider;

import android.content.Context;
import android.content.res.XmlResourceParser;
import android.content.res.TypedArray;
import android.util.Xml;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InflateException;
import android.text.TextUtils;

import java.util.ArrayList;
import java.io.IOException;

import org.marcpoppleton.strawberry.R;
import org.xmlpull.v1.XmlPullParserException;
import static org.xmlpull.v1.XmlPullParser.*;

public final class PairedValuesFactory {

    private static final String LOG_TAG = "StrawberryParser";
    private static final String TAG_PAIRS = "pairs";
    private static final String TAG_PAIR = "pair";


    private PairedValuesFactory() {
    }

    public static PairedValue[] getValues(Context context, int resource) {
    	final ArrayList<PairedValue> values = new ArrayList<PairedValue>();
        final XmlResourceParser parser = context.getResources().getXml(resource);

        try {
            inflate(context, parser, values);
        } catch (IOException e) {
            Log.w(LOG_TAG, "An error occured while loading the values", e);
        } catch (XmlPullParserException e) {
            Log.w(LOG_TAG, "An error occured while loading the values", e);            
        } finally {
            parser.close();
        }

        return values.toArray(new PairedValue[0]);
    }

    private static void inflate(Context context, XmlResourceParser parser,
            ArrayList<PairedValue> pairs) throws IOException, XmlPullParserException {

        final AttributeSet attrs = Xml.asAttributeSet(parser);

        int type;
        while ((type = parser.next()) != START_TAG && type != END_DOCUMENT) {
            // Empty
        }

        if (type != START_TAG) {
            throw new InflateException(parser.getPositionDescription() + ": No start tag found!");
        }

        final String name = parser.getName();
        if (TAG_PAIRS.equals(name)) {
            parsePairs(context, parser, attrs, pairs);
        } else {
            throw new InflateException(parser.getPositionDescription() +
                    ": The root tag must be " + TAG_PAIRS);
        }
    }

    private static void parsePairs(Context context, XmlResourceParser parser, AttributeSet attrs,
            ArrayList<PairedValue> values) throws IOException, XmlPullParserException {

        final int depth = parser.getDepth();

        int type;
        while (((type = parser.next()) != END_TAG || parser.getDepth() > depth) &&
                type != END_DOCUMENT) {

            if (type != START_TAG) {
                continue;
            }

            final String name = parser.getName();
            if (TAG_PAIR.equals(name)) {
                addPair(context, parser, attrs, values);
            }
        }
    }

    private static void addPair(Context context, XmlResourceParser parser, AttributeSet attrs,
            ArrayList<PairedValue> values) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PairedValue);
        final String key = a.getString(R.styleable.PairedValue_key);
        if (TextUtils.isEmpty(key)) {
            throw new InflateException(parser.getPositionDescription() +
                    ": A pair must have a key");
        }

        final String value = a.getString(R.styleable.PairedValue_value);
        if (TextUtils.isEmpty(value)) {
            throw new InflateException(parser.getPositionDescription() +
                    ": A pair must have a value");
        }

        a.recycle();

        PairedValue pair = new PairedValue(key.subSequence(0,key.length()), value.subSequence(0,value.length()));
        values.add(pair);
    }
}
